package com.demo.pong.controller;

import com.demo.pong.service.PongService;
import jakarta.annotation.Resource;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;
import reactor.core.publisher.Mono;

/**
 *  @author Jofo
 */
@Slf4j
@RestController
public class PongController {
    @Resource
    private PongService pongService;

    /**
     * Handles GET requests in response to "pong" messages from the client
     *
     * @param msg the content of the message sent by the msg client
     * @param traceId is a unique identifier used to trace the request
     * @return Mono<ResponseEntity> object containing the response message<String>
     */
    @GetMapping("/pong")
    public Mono<ResponseEntity<String>> pongMsg(@RequestParam("msg") @NonNull String msg, @RequestParam("traceId") String traceId) {
        // The service layer method is invoked to process the message and map the result to an HTTP response
        return pongService.respond(msg, traceId)
                .map(ResponseEntity::ok)
                .onErrorResume(e -> {
                    log.error("Error in pongMsg: ", e);
                    if (e instanceof ResponseStatusException responseStatusException &&
                                    responseStatusException.getStatusCode() == HttpStatus.TOO_MANY_REQUESTS) {
                        // If the error is due to too many requests, a 429 status code and error message are returned
                        return Mono.just(ResponseEntity.status(responseStatusException.getStatusCode().value())
                            .body(responseStatusException.getMessage() + ", traceId: " + traceId));
                    }else {
                        // For other errors, a 500 status code and error message are returned
                        return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
                            .body("Error: " + e.getClass().getSimpleName() + ": " + e.getMessage() + ", traceId: " + traceId));
                    }
                });
    }
}
